#pragma once
#include "Socket.hpp"
#include "Comm.hpp"
#include "Log.hpp"
#include "Epoller.hpp"
#include <memory>
#include <string>
static const int defaultnum = 5;
class EpollServer
{
public:
    EpollServer(uint16_t port)
        :_port(port)
        , _listensock(new TcpSocket)
        , _epoller(new Epoller)
    {}
    void Init()
    {
        _listensock->CreateListenSocket(_port);
        
        _epoller->AddEvent(_listensock->GetSockfd(), EPOLLIN);
        for(int i = 0; i < defaultnum; i++)
            memset(&_events[i], 0, sizeof(epoll_event));
    }
    void Loop()
    {
        while(true)
        {
            _epoller->PrintDebug();
            int n = _epoller->Wait(_events, defaultnum, 5000);
            if(n == 0)
                lg.LogMessage(Error, "timeout...\n");
            else if(n == -1)
                lg.LogMessage(Error, "client quit, errno: %d:%s\n", errno, strerror(errno));
            else
            {
                lg.LogMessage(Info, "有事件就绪\n");
                HandlerRequest(n);
            }
        }
    }
    void HandlerRequest(int n)
    {
        for(int i = 0; i < n; i++)
        {
            uint32_t events = _events[i].events;
            int fd = _events[i].data.fd;
            if(events & EPOLLIN)
            {
                if(fd == _listensock->GetSockfd())
                {
                    std::string clientip;
                    uint16_t clientport;
                    int clientfd = _listensock->AcceptConnection(clientip, clientport);
                    if(clientfd > 0)
                    {
                        _epoller->AddEvent(clientfd, EPOLLIN);
                        lg.LogMessage(Info, "connect success, clientfd:%d\n", clientfd);
                    }
                    else
                        lg.LogMessage(Warning, "connect falied, errno:%d:%s\n", errno, strerror(errno));
                }
                else
                {
                    char request[1024];
                    int n = recv(fd, request, 1023, 0);
                    if(n > 0)
                    {
                        request[n] = 0;
                        std::string response = "server# ";
                        response += request;
                        send(fd, response.c_str(), response.size(), 0);
                    }
                    else
                    {
                        if(n < 0)
                            lg.LogMessage(Warning, "recv error, errno:%d:%s\n", errno, strerror(errno));
                        else if(n == 0)
                            lg.LogMessage(Info, "read EOF or client quit, errno:%d:%s\n", errno, strerror(errno));

                        _epoller->DelEvent(fd, EPOLLIN);    //我的版本中，这里的顺序不一样，没有bug
                        close(fd);
                    }

                }
            }
        }
    }
    ~EpollServer()
    {
    }
private:
    uint16_t _port;
    std::unique_ptr<Socket> _listensock;
    std::unique_ptr<Epoller> _epoller;
    struct epoll_event _events[defaultnum];

};